#include "StdAfx.h"
#include "block.h"
#include "stdlib.h"
#include "math.h"
#include "stdio.h"


block::block(void)
{
}

block::~block(void)
{
}

///////////////////////////////////////////////////////////////////////////
//"Overloaded" assignment operator for SVECTOR struct
//Copies Source into Destination field by field.
//////////////////////////////////////////////////////////////////////////


void block::CopyVector(PSVECTOR sDestination,  PSVECTOR  sSource)
{
	sDestination->Absolute = sSource->Absolute;
	sDestination->iValue = sSource->iValue;
	sDestination->iCycles = sSource->iCycles;
}

///////////////////////////////////////////////////////////////////////////
//"Overloaded" assignment operator for SLOOP struct
//Copies Source into Destination field by field.
//////////////////////////////////////////////////////////////////////////

void block::CopyLoop(PSLOOP sDestination, PSLOOP sSource)
{
	sDestination->iLength = sSource->iLength;
	sDestination->iLoopCount = sSource->iLoopCount;
}

///////////////////////////////////////////////////////////////////////////
//"Overloaded" assignment operator for SBLOCK struct
//Copies Source into Destination field by field.
//////////////////////////////////////////////////////////////////////////

void block::CopyBlock(PSBLOCK sDestination, PSBLOCK sSource)
{
	sDestination->LoopOrFlat =	sSource->LoopOrFlat;
	sDestination->sFirst =		sSource->sFirst;
	sDestination->sLast =		sSource->sLast;
	
	CopyLoop(sDestination->sLoopData,sSource->sLoopData);
}


//////////////////////////////////////////////////////////////////////////
//"Overloaded" == operator for SLINE struct
//Compares Lines, Vector by Vector. 
//Returns 0 if Lines are identical, 1 otherwise
//////////////////////////////////////////////////////////////////////////

int block::LinesCompare(PSLINE sOne, PSLINE sTwo)
{
	int i = 0;
	int j = 0;
	int iLength1;
	int iLength2;

	iLength1 = sOne->sLast - sOne->sFirst + 1;
	iLength2 = sTwo->sLast - sTwo->sFirst + 1;

	while ( i < iLength1 && j < iLength2 )
	{
		if ( (sOne->sFirst + i)->iCycles == 0 )
		{
			i ++; 
			continue;
		}
		if ( (sTwo->sFirst + j)->iCycles == 0 )
		{
			j ++;
			continue;
		}
		if ( mencoding.VectorsCompare(((sOne->sFirst) + i), ((sTwo->sFirst) + j)) != 0 )
		{
			return 1;
		}
		
		i ++;
		j ++;
	}
	//There is a tail
	if (i < iLength1 || j < iLength2)
	{
		return 1;
	}

	
	return 0;
}


///////////////////////////////////////////////////////////////////////////////////
//LoopsCompare:
//Compares two LOOP blocks by their compressed(encoded) size
//Returns 2 if sLoop2 is better, 1 if they are the same or sLoop1 is better.
/////////////////////////////////////////////////////////////////////////////////

int block::LoopsCompare(PSBLOCK sLoop1, PSBLOCK sLoop2)
{
	unsigned int	iDummy[1500];
	int				iSizeOfBody1;
	int				iSizeOfBody2;
	int				iSavedSpace1;
	int				iSavedSpace2;
	int				tmp;


	iSizeOfBody1 = mencoding.Encode((sLoop1->sFirst), (sLoop1->sLast), iDummy, DEPENDANT, &tmp);
	iSizeOfBody2 = mencoding.Encode((sLoop2->sFirst), (sLoop2->sLast), iDummy, DEPENDANT, &tmp);
	
	//How many code words will be saved if we use loop markers. 
	//Each loop marker takes 1 code word => 2 + iSizeOfBody
	iSavedSpace1 = iSizeOfBody1 * sLoop1->sLoopData->iLoopCount - (2 + iSizeOfBody1);
	iSavedSpace2 = iSizeOfBody2 * sLoop2->sLoopData->iLoopCount - (2 + iSizeOfBody1);

	if (iSavedSpace1 < iSavedSpace2)
	{
		return 2;
	}
	//Logical else
	return 1;
}

/////////////////////////////////////////////////////////////////////////
//Inflate:
//Add NumberOfNew new cells in Array, starting from iIndex+1.
//Size is current size of the array and it is updated accordingly.
//Return value : 1 upon success 0 upon fail(and then sArray is not changed)
/////////////////////////////////////////////////////////////////////////


int block::Inflate(PSBLOCK* sArray, int* iSize, int iIndex, int iNumberOfNew)
{
	int i;
	PSBLOCK tmp;

	//Updating size
	*iSize += iNumberOfNew;


	tmp = (PSBLOCK)realloc(*sArray,(*iSize)*sizeof(SBLOCK));
	if (tmp == NULL)
	{
		return 0;
	}

	*sArray = tmp;

	for (i = *iSize - iNumberOfNew ; i < *iSize; i ++)
	{
		(*sArray)[i].sLoopData = (PSLOOP)malloc(sizeof(SLOOP));
	}

	//Creating empty cells in the desired place
	//By definition we want empty cells to start in iIndex+1
	for (i = iIndex + iNumberOfNew + 1; i < *iSize; i++)
	{
		CopyBlock(*sArray + i,*sArray + i - iNumberOfNew);
	}


	return 1;

}



////////////////////////////////////////////////////////////////////////
//FindLines:
//Building the Line Array: pointer to beginning and end of lines
//Lines are indicate by activeness of Hsync
//A "dead area" (where Hsync is active) before a line is "in" that line
//Meaning : line  = dead area + the actual line (till the next dead area)
//Return Value: number of found lines
///////////////////////////////////////////////////////////////////////////

int block::FindLines(PSVECTOR sVectorArray, int iNumOfVectors, int iHsyncBit, EFFECTIVE_EDGE iEffEdge, PSLINE* sLineArray)
{
	//Used to identify value of Hsync
	int iHsyncMask;
	
	//Index in sVectorArray
	int iVectorIndex = 0;
	//Index in sLineArray
	int iLineIndex = 0;
	
	//Indicates is this the middle of a line or not
	int iInLine = 0;
	//Total number of lines found - for statistics
	int iLinesNumber = 0;
	
	//Mask to retrieve Hsync value
	iHsyncMask = 1 << iHsyncBit ;
	

	while ( iVectorIndex < iNumOfVectors )
	{
		//Look for first Vector with active Hsync bit
		while (	(sVectorArray[iVectorIndex].iValue & iHsyncMask) != 
				(iEffEdge << iHsyncBit) &&
				iVectorIndex < iNumOfVectors )
		{
			if (sVectorArray[iVectorIndex].iCycles == 0)
			{
				iVectorIndex ++;
			}
			iVectorIndex ++;
		}
		//Vector with active Hsync bit was found
		//This is the beginning of a dead area - end of this line (if we are in a line)
		//and beginning of a new line
		
		if (iVectorIndex >= iNumOfVectors)
		{
			continue;
		}
		if (iInLine) 
		{
			//Irrelevant vector
			if (sVectorArray[iVectorIndex - 1].iCycles == 0)
			{
				iVectorIndex ++;
			}

			(*sLineArray)[iLineIndex].sLast = (sVectorArray + iVectorIndex -1);
			iInLine = 0;

			//DEBUG
			/*printf("Line  %d ends in vector %d,%d\n",
					iLineIndex,
					(sVectorArray + iVectorIndex - 1)->iValue,
					(sVectorArray + iVectorIndex - 1)->iCycles);
			*/
			iLineIndex ++;

			//For statistics
			iLinesNumber ++;
			/*printf("This is line number %d, it has %d vectors, ending in vector %d\n\n",
					iLinesNumber - 1,
					(*sLineArray)[iLineIndex-1].sLast - (*sLineArray)[iLineIndex-1].sFirst + 1,
					iVectorIndex - 1);
			*/
		
		}

		//Is there anywhere to continue or was that the last vector
		if (iVectorIndex >= iNumOfVectors)
		{
			break;
		}
		//Including the dead area before the line 
		if (sVectorArray[iVectorIndex].iCycles == 0)
		{
			iVectorIndex ++;
		}
		(*sLineArray)[iLineIndex].sFirst = (sVectorArray + iVectorIndex);
		iInLine = 1;

		//DEBUG
		/*printf("Line  %d starts in vector %d,%d\n",
				iLineIndex,
				(sVectorArray + iVectorIndex)->iValue,
				(sVectorArray + iVectorIndex)->iCycles);
		*/
		//Look for the last Vector with active Hsync bit.
		//Need to run this loop to be able to look for next line easily
		while (((sVectorArray[iVectorIndex].iValue & iHsyncMask) == (iEffEdge << iHsyncBit))&&
				iVectorIndex < iNumOfVectors)
		{
			iVectorIndex ++;
		}
		//Now *this* is the "real" beginning of the line (end of dead area + 1)
		
		//Continue to next Vector
		//iVectorIndex ++;
	}
	//never got to the end of the line cause there was no next line
	if (iInLine)
	{
		(*sLineArray)[iLineIndex].sLast = (sVectorArray + iNumOfVectors - 1);
		iInLine = 0; //Not used
		
		//DEBUG
		/*printf("Line  %d end in vector %d,%d\n",
				iLineIndex,
				(*sLineArray)[iLineIndex].sLast->iValue,
				(*sLineArray)[iLineIndex].sLast->iCycles);
		*/	
		iLineIndex ++;

		//For statistics
		iLinesNumber ++;
		/*printf("This is line number %d, it has %d vectors, ending in vector %d\n\n",
					iLinesNumber - 1,
					(*sLineArray)[iLineIndex-1].sLast - (*sLineArray)[iLineIndex-1].sFirst + 1,
					iVectorIndex - 1);
			*/
	}
	return iLinesNumber;

}



int block::Round(double iValue, ROUND iRound)
{
	switch(iRound)
	{
	case FLOOR:
		return (int)(floor(iValue));
	case CEILING:
		return (int)(ceil(iValue));
	case CLOSEST:
		return (int)((iValue > 0) ? iValue + 0.5 : iValue - 0.5);
	}
	//should never happen
	printf("Non valid round method. Exiting..\n");
	exit(0);
	return 0;
}



int block::ToCycles1(PSVECTOR* sFirstVector, int iNumberOfVectors, double ClockCycle, ROUND iRound, PSUTG_SIGNAL sSignals, double RefTime)
{
	int i;
	int iSignal;
	double epsilon;
	double tmp;
	for (i = 0; i < iNumberOfVectors - 1 ; i++)
	{
		
#ifdef ERROR_CORRECTION
		tmp = (*sFirstVector)[i + 1].Absolute/ClockCycle; 
		epsilon = (*sFirstVector)[i + 1].Absolute - 
					Round(tmp,iRound) * ClockCycle;
		ClockCycle = ClockCycle + (ALPHA * epsilon);
		//if (i%1 == 0) printf ("Clock is now(%d) = %10.6f, epsilon=%10.6f\n",i,ClockCycle, epsilon); 
#endif
		iSignal = mencoding.IdentifyChange((*sFirstVector)[i].iValue,(*sFirstVector)[i+1].iValue, OFF);
		(*sFirstVector)[i+1].Absolute = 
			Round(((*sFirstVector)[i+1].Absolute - 
					sSignals[iSignal].Phase - 
					RefTime)/ClockCycle
					,CLOSEST);
	}
	return 1;

}



int block::ToCycles(PSLINE* sLineArray, int iNumberOfLines, double ClockCycle, ROUND iRound, PSUTG_SIGNAL sSignals, unsigned long ulHtotal)
{
	int i;
	int j;
	int iVectorsInLine;
	int iSignal;
	double RefTime;
	//double epsilon;
	//double tmp;
	for (i = 0; i < iNumberOfLines ; i++)
	{	

		iVectorsInLine = (*sLineArray)[i].sLast - (*sLineArray)[i].sFirst + 1;
		RefTime = ((*sLineArray)[i].sFirst)->Absolute;
		for (j = 0; j < iVectorsInLine ; j ++)
		{
			if (j == 0 ) 
			{
				iSignal = HIS;
			}
			else
			{
				iSignal = mencoding.IdentifyChange(((*sLineArray)[i].sFirst +j)->iValue,
										  ((*sLineArray)[i].sFirst +j - 1)->iValue, 
										  OFF);
			}
			((*sLineArray)[i].sFirst +j)->Absolute = 
					Round((((*sLineArray)[i].sFirst +j)->Absolute - 
							sSignals[iSignal].Phase - RefTime)/ClockCycle,
							iRound) 
					+ i * ulHtotal;
		}
		/*if (i != iNumberOfLines - 1)
		{
			iSignal = IdentifyChange(((*sLineArray)[i].sLast)->iValue,
									  ((*sLineArray)[i +1].sFirst)->iValue, 
									  OFF);
			(*sLineArray)[i].sLast->Absolute = 
					Round((((*sLineArray)[i].sLast)->Absolute - 
							sSignals[iSignal].Phase - RefTime)/ClockCycle,
							iRound) 
					+ i * ulHtotal;
		}
		*/

	}
	return 1;

}


///////////////////////////////////////////////////////////////////////////
//Update the Cycles field in all vectors starting from FirstVector
//with number of cencor clock cycles during which the vector is relevant
//This function must be called BEFORE MarkLoops
//Return value is number of relevant vectors that are left after the function is done  
//Assumption: for each Vector array this function will be called once!
//////////////////////////////////////////////////////////////////////////////


int block::UpdateCycles(PSVECTOR* sFirstVector, int iNumberOfVectors, double ClockCycle, ROUND iRound, unsigned long ulHtotal, unsigned long ulVtotal)
{
	int i;
	//double epsilon;
//	double tmp;
	int iZeroCounter = 0;

	//Extra vector exists for reference
	for (i = 0; i < iNumberOfVectors - 1 ; i++)
	{
		
		(*sFirstVector)[i].iCycles = 
			(int)((*sFirstVector)[i + 1].Absolute - (*sFirstVector)[i].Absolute);

		
		//Previous Vector is irrelevant
		if ((*sFirstVector)[i].iCycles == 0)
		{
			/*(*sFirstVector)[i - 1].iValue = (*sFirstVector)[i].iValue;
			(*sFirstVector)[i - 1].iCycles = 
			Round((*sFirstVector)[i + 1].Absolute/ClockCycle,iRound) - 
		    Round((*sFirstVector)[i - 1].Absolute/ClockCycle,iRound);
				//	Round(((*sFirstVector)[i + 1].Absolute/ClockCycle - 
			//	(*sFirstVector)[i - 1].Absolute/ClockCycle),iRound);

			(*sFirstVector)[i].iCycles = 0; //Making previous vector irrelevant*/
			iZeroCounter ++;
		}

	}
	(*sFirstVector)[i].iCycles =(int)(ulHtotal * ulVtotal - (*sFirstVector)[i].Absolute);
	
	//NEED TO CHANGE?
	return iNumberOfVectors - iZeroCounter;
}



/////////////////////////////////////////////////////////////////////////
//MarkLoops:
//Builds the sBlockArray. (Array of blocks, built respectively to order
//of Vectors in sLineArray).
//sLineArray is Array of Lines, which infact represent the array of Vectors,
//jut devided to Lines.
//Looks for loops (sized within range [1 line, MaxLoopSize lines]
//in sLineArray. Optimal (according to LoopsCompare) loops are stored 
//as LOOP blocks in sBlockArray. Flat areas (where there are no loops)
//are stored as FLAT blocks in sBlockArray.
//Return value is number of the blocks - iBlockIndex.
//
//Assumptions:
//1. sBlockArray is big enough to accamulate all blocks
//2. UpdateCycles was called before calling this function
/////////////////////////////////////////////////////////////////////////

int block::MarkLoops(PSLINE sLineArray, int iNumOfLines, PSBLOCK* sBlockArray, int iMaxLoopSize)
{
	//Index in the sSequenceArray
	int iBlockIndex = 0;
	//Beginning of loop
	int i = 0;
	//Cursor to run with when looking for end of loop
	int k = 0;
	//Used to find the length of loop body
	int j = 0;
	//Flag to indicate is this the first time we look from Array[i] (=1) or not(=0)
	int iFirstTime = 1;
	//Flag to indicate were loops (starting from Array[i]) found (=0) or not (=1)
	int iNoLoopsYet = 1;
	//Flag to indicate are we in the middle of a flat block
	int iIsFlat = 0;
	//Total length of the loop
	int iTotalLength =0;

	//Number of found loops for statistics.
	int iLoopsNumber = 0;

	
	//Parameters of the currently found loop (to compare with the loops found before)
	SBLOCK sCurrent;
	
	//Parameters of the best loop found so far
	SBLOCK sBest;
	
	sCurrent.sLoopData = (PSLOOP)malloc(sizeof(SLOOP));
	sBest.sLoopData = (PSLOOP)malloc(sizeof(SLOOP));
	
	sCurrent.LoopOrFlat =	LOOP;
	sBest.LoopOrFlat =		LOOP;
	

	
	if (iNumOfLines == 1)
	{
		(*sBlockArray)[iBlockIndex].LoopOrFlat = FLAT;
		(*sBlockArray)[iBlockIndex].sFirst = sLineArray[i].sFirst;
		iIsFlat = 1;



		//Statistics:
		printf("Block number %d is FLAT, starts in line %d  ",
				iBlockIndex,
				i);
	
		i ++ ;
	}

	//Looking for loops:
	//For each Line in sLineArray choose the best(by CompareLoop) legal loop
	while(i < iNumOfLines )
	{
		
		//Start comparing from the adjacent element
		if (iFirstTime)
		{
			j = i+1;
		}
		
		//Look for the first element sLineArray[j] that is equal to sLineArray[i] 
		while	( ( j < iNumOfLines ) && ( (j-i) <= iMaxLoopSize ) &&
				( (LinesCompare(sLineArray + i , sLineArray + j) != 0)  ) )
		{
			j++;
		}
		
		//There are no more elements equal to sLineArray[i] within MAX_LOOP_SIZE
		if ( (j-i) >= iMaxLoopSize+1 || j >= iNumOfLines )
		{
			//No loops were found  - a FLAT block
			if (iNoLoopsYet) 
			{
			/*	(*sBlockArray)[iBlockIndex].LoopOrFlat = FLAT;
				//Not Connective block, but a new one
				if ((*sBlockArray)[iBlockIndex].sLast + 1 != sLineArray[i].sFirst)
				{
					//New block
					iBlockIndex++;
					//New first Vector
					(*sBlockArray)[iBlockIndex].sFirst = sLineArray[i].sFirst;
				}
				//Last Vector needs to be updated anyway
				(*sBlockArray)[iBlockIndex].sLast = sLineArray[i].sLast;
				
				//Statistics:
				printf("Block number %d is FLAT, starts in line %d, takes %d lines\n",
						iBlockIndex,
						i,
						(*sBlockArray)[iBlockIndex].sLast - 
						(*sBlockArray)[iBlockIndex].sFirst);
			*/	
				//Mark start of FLAT block 
				if (iIsFlat == 0)
				{
					(*sBlockArray)[iBlockIndex].LoopOrFlat = FLAT;
					(*sBlockArray)[iBlockIndex].sFirst = sLineArray[i].sFirst;
					iIsFlat = 1;



					//Statistics:
					printf("Block number %d is FLAT, starts in line %d  ",
							iBlockIndex,
							i);
				}
				//Look where the next loop will start
				i ++ ;
			}
			//Loops were found - a LOOP block, the best loop saved in sBest
			//Need to mark the relevant Vectors
			else
			{
				//If this loop is the end of a flat block this needs to be marked
				if (iIsFlat)
				{
					(*sBlockArray)[iBlockIndex].sLast = sLineArray[i - 1].sLast;
					iIsFlat = 0;
					//Statistics:
					printf ("ends in line %d\n", i-1);
					
				/*	for (k = 0; k < ((*sBlockArray)[iBlockIndex].sLast - 
									(*sBlockArray)[iBlockIndex].sFirst + 1);
										k ++)
					{
					printf("vector %d: %x,%x\n", k, 
								((*sBlockArray)[iBlockIndex].sFirst + k)->iValue,
								((*sBlockArray)[iBlockIndex].sFirst + k)->iCycles);
										}
*/
						

					iBlockIndex ++;
				}

				iTotalLength = sBest.sLoopData->iLength * sBest.sLoopData->iLoopCount;
				
				CopyBlock( &((*sBlockArray)[iBlockIndex]), &sBest);
				
				
				
				//Adding the loop found to total number of loops - for statistics
				iLoopsNumber ++;
				//Statistics
				printf("Block number %d is LOOP, starts in line %d\n", 						
						iBlockIndex,
						i);
				printf("body takes %d lines, repeats %d times\n",
						(*sBlockArray)[iBlockIndex].sLoopData->iLength,
						(*sBlockArray)[iBlockIndex].sLoopData->iLoopCount);

				iBlockIndex++;
				i += iTotalLength;
			}
			//Done with this i
			iFirstTime = 1;
			iNoLoopsYet = 1;
			continue;
		}
		
		//A loop was found!
		//Need to run on indeces starting from i, but want to save i
		k=i;
		
		//Length of the body of the found loop
		sCurrent.sLoopData->iLength = j-i;

		//Run with k and j till they don't match
		while (  (j<iNumOfLines) && (LinesCompare(sLineArray +k ,sLineArray +j) == 0))
		{
			j++;
			
		}
		
		//++j happened even though the loop ended  - DID IT?
		//j--;

		//Updating the current loop - to compare with the saved in sBest
		
		sCurrent.sLoopData->iLoopCount =	(j-i)/sCurrent.sLoopData->iLength;
		//Not a real LOOP - repeats 1 time, we'll look for another one..
		if (sCurrent.sLoopData->iLoopCount == 1)
		{
			iFirstTime = 0;
			continue;
		}
		sCurrent.sFirst =					sLineArray[i].sFirst;
		//iTotalLength = sCurrent.sLoopData->iLength * sCurrent.sLoopData->iLoopCount;			
		sCurrent.sLast =					sLineArray[i + sCurrent.sLoopData->iLength - 1].sLast;

		//Check if current loop is better form saved in sBest or it is the 
		//first loop found
		if ((iNoLoopsYet) || (LoopsCompare(&sBest,&sCurrent) == 2))
		{
			//Updating the fields of sLoop with the current loop
			CopyBlock(&sBest,&sCurrent);
		}
		//The next loop will not be the first.
		iNoLoopsYet = 0;
		iFirstTime = 0;
	}//end of while
	//We never found a last loop and there is an "open" flat block 
	if (iIsFlat)
	{
		(*sBlockArray)[iBlockIndex].sLast = sLineArray[iNumOfLines - 1].sLast;
		iIsFlat = 0;
		//Statistics:
		printf ("ends in line %d\n", iNumOfLines - 1);
		 
		iBlockIndex ++;
	}

	
	//Statistics:
	printf("Number of found loops : %d \n", iLoopsNumber);

	return iBlockIndex;
}


///////////////////////////////////////////////////////////////////////////////////////
//FindmoreLoops:
//Tries to find small (not in Line units, but in Vectors units) loops in FLAT
//blocks or in LOOP blocks whose loop body is bigger the MaxLoopSize
//Assumption: MarkLoops was performed befor calling this function
/////////////////////////////////////////////////////////////////////////////////////////
 

int block::FindMoreLoops(PSBLOCK* sBlockArray, int iNumberOfBlocks, int iMaxLoopSize)
{
	int iBlockIndex = 0;
	int iLongVectors = 0;
	int i;
	int k;
	int j;
	int iVectorsInBlock; 
	//Number of cells added to BlockArray (updated for each FLAT)
	int iAdded;
	
	//Maximum number of vectors in LOOP. Calculated assuming each 
	//Vector will be encoded as Long Vector (2 dwords)
	int iMaxVectorsInLoop;
	
	//Cursor 
	PSVECTOR psFirst;
	
	//Indicator - is this the first time we deal with this i
	int iFirstTime = 1;
	
	//Indicator - were there loops found for this i
	int iNoLoopsYet = 1;
	
	//Total length of the loop
	int iTotalLength;

	//Number of found loops for statistics.
	int iLoopsNumber = 0;
	
	//Flag to indicate are we in the middle of a flat block
	int iIsFlat = 0;
	
	//Number of blocks
	int iCurrentSize;
	
	//Parameters of the currently found loop (to compare with the loops found before)
	SBLOCK sCurrent;
	
	//Parameters of the best loop found so far
	SBLOCK sBest;
	
	
	sCurrent.sLoopData = (PSLOOP)malloc(sizeof(SLOOP));
	sBest.sLoopData = (PSLOOP)malloc(sizeof(SLOOP));
	
	sCurrent.LoopOrFlat =	LOOP;
	sBest.LoopOrFlat =		LOOP;

	//MaxLoopSize is in bytes, assume worst case - 2 dwords for each vector
	iMaxVectorsInLoop = iMaxLoopSize / (2 * BYTES_IN_CODE_WORD);

	iCurrentSize = iNumberOfBlocks;
	
	while( iBlockIndex < iNumberOfBlocks )
	{
		
		//If this block is a LOOP of legal size - nothing to do
		if ( (*sBlockArray + iBlockIndex)->LoopOrFlat == LOOP  &&
			 mencoding.Encode( (*sBlockArray + iBlockIndex)->sFirst,
					 (*sBlockArray + iBlockIndex)->sLast, NULL, DEPENDANT, &iLongVectors ) 
					 <= iMaxLoopSize )
		{
			iBlockIndex ++; 
			continue;
		}

		iVectorsInBlock = (*sBlockArray + iBlockIndex)->sLast - 
						  (*sBlockArray + iBlockIndex)->sFirst + 1;

		//LOOP with body too big is flattened and treated next iteration
		if ( (*sBlockArray + iBlockIndex)->LoopOrFlat == LOOP )
		{
			(*sBlockArray + iBlockIndex)->LoopOrFlat = FLAT;
			(*sBlockArray + iBlockIndex)->sLast = 
				(*sBlockArray + iBlockIndex)->sFirst + 
				(((*sBlockArray + iBlockIndex)->sLoopData->iLoopCount) * 
					iVectorsInBlock) - 1;
			continue;
		}
		
		//Now we know this is a flat block we are dealing with	
		//Looking for loops:
		psFirst = (*sBlockArray + iBlockIndex)->sFirst;
		iAdded = 0;
		i = 0;
		iFirstTime = 1;
		iNoLoopsYet = 1;
		iIsFlat = 0;

		
		while(i < iVectorsInBlock - 1)
		{
			
			//Start comparing from the adjacent element
			if (iFirstTime)
			{
				j = i+1;
			}
			
			//Look for the first element psFirst+j that is equal to psFirst+i 
			while	( ( j < iVectorsInBlock ) && ( (j-i) <= iMaxVectorsInLoop ) &&
					( (mencoding.VectorsCompare(psFirst + i , psFirst + j) != 0)  ) )
			{
				j++;
			}
			
			//There are no more elements equal to psFirst+i within iMaxVectorsInLoop 
			if ( (j-i) >= iMaxVectorsInLoop + 1 || j >= iVectorsInBlock )
			{
				//No loops were found  - a FLAT block
				if (iNoLoopsYet) 
				{
					
					//Mark start of FLAT block 
					if (iIsFlat == 0)
					{
						(*sBlockArray)[iBlockIndex + iAdded].LoopOrFlat = FLAT;
						(*sBlockArray)[iBlockIndex + iAdded].sFirst = psFirst + i;
						iIsFlat = 1;



						//Statistics:
						printf("Block number %d is FLAT, starts in vector %d  ",
								iBlockIndex + iAdded,
								i);
					}
					//Look where the next loop will start
					i ++ ;
				}
				//Loops were found - a LOOP block, the best loop saved in sBest
				//Need to mark the relevant Vectors
				else
				{
					//If this loop is the end of a flat block this needs to be marked
					if (iIsFlat)
					{
						(*sBlockArray)[iBlockIndex + iAdded].sLast = psFirst + i - 1;
						iIsFlat = 0;
						
						//Add two empty cells in BlockArray, starting from iBlockIndex + 
						//iAdded + 1. First will be the found loop, next will be the 
						//next block (after the loop). Done for efficiency.
						//The right thing algorythmically would be to add one
						//cell now and one after the loop is registered.
						Inflate(sBlockArray, &iCurrentSize, iBlockIndex + iAdded, 2);

						//Update current block index 
						iAdded ++;

						
						//Statistics:
						printf ("ends in vector %d\n", i-1);
						
					/*	for (k = 0; k < ((*sBlockArray)[iBlockIndex].sLast - 
										(*sBlockArray)[iBlockIndex].sFirst + 1);
											k ++)
						{
						printf("vector %d: %x,%x\n", k, 
									((*sBlockArray)[iBlockIndex].sFirst + k)->iValue,
									((*sBlockArray)[iBlockIndex].sFirst + k)->iCycles);
											}
	*/
							

					}
					//Register the found loop
					iTotalLength = sBest.sLoopData->iLength * sBest.sLoopData->iLoopCount;
					
					CopyBlock( &((*sBlockArray)[iBlockIndex + iAdded]), &sBest);
					
					
					
					//Adding the loop found to total number of loops - for statistics
					iLoopsNumber ++;
					
					
					//Statistics
					printf("Block number %d is LOOP, starts in vector %d\n", 						
							iBlockIndex + iAdded,
							i);
					printf("body takes %d vectors, repeats %d times\n",
							(*sBlockArray)[iBlockIndex + iAdded].sLoopData->iLength,
							(*sBlockArray)[iBlockIndex + iAdded].sLoopData->iLoopCount);

					iAdded ++;
					i += iTotalLength;


				}
				//Done with this i
				iFirstTime = 1;
				iNoLoopsYet = 1;
				continue;
			}
			
			//A loop was found!
			//Need to run on indeces starting from i, but want to save i
			k=i;
			
			//Length of the body of the found loop
			sCurrent.sLoopData->iLength = j-i;

			//Run with k and j till they don't match
			while ((mencoding.VectorsCompare(psFirst +k ,psFirst +j) == 0) && (j < iVectorsInBlock))
			{
				j++;
				k++;
			}
			
			//++j happened even though the loop ended  - DID IT?
			//j--;

			//Updating the current loop - to compare with the saved in sBest
			
			sCurrent.sLoopData->iLoopCount = (j - i) / sCurrent.sLoopData->iLength;
			//Not a real LOOP - repeats 1 time, we'll look for another one..
			if (sCurrent.sLoopData->iLoopCount == 1)
			{
				iFirstTime = 0;
				continue;
			}
			sCurrent.sFirst = psFirst + i;
			sCurrent.sLast =  psFirst + i + sCurrent.sLoopData->iLength - 1;								

			//Check if current loop is better form saved in sBest or it is the 
			//first loop found
			if ((iNoLoopsYet) || (LoopsCompare(&sBest,&sCurrent) == 2))
			{
				//Updating the fields of sLoop with the current loop
				CopyBlock(&sBest,&sCurrent);
			}
			//The next loop will not be the first.
			iNoLoopsYet = 0;
			iFirstTime = 0;
		}//end of looking for loops in this FLAT
		//We never found a last loop and there is an "open" flat block 
		if (iIsFlat)
		{
			(*sBlockArray)[iBlockIndex + iAdded].sLast = psFirst + iVectorsInBlock - 1; 
			iIsFlat = 0;
			iAdded ++;
			//Statistics:
			printf ("ends in vector %d\n", iVectorsInBlock - 1);
			 
		}
		iNumberOfBlocks += iAdded - 1;
		iBlockIndex += iAdded;
		
	}

	//Statistics:
	printf("Number of found loops : %d \n", iLoopsNumber);

	return iBlockIndex;
}


///////////////////////////////////////////////////////////////////////////////
//Merge two VectorArrays, both sorted by Absolute field.
//////////////////////////////////////////////////////////////////////////


int block::Merge(const PSVECTOR sFastVectorArray, int iVectorsInFast, const PSVECTOR sSlowVectorArray, int iVectorsInSlow, PSVECTOR* sMergedVectorArray)
{

	int iSlow =		0;
	int iFast =		0;
	int iMerged =	0;
	int i =			0;
	int iTail =		0;
 

	//Dummy vector
	//(*sMergedVectorArray)[0].Absolute = 0;
	//(*sMergedVectorArray)[0].iValue = 0;

	for (iMerged = 0;( (iSlow < iVectorsInSlow) && (iFast < iVectorsInFast) ); iMerged ++)
	{
		
		if (sFastVectorArray[iFast].Absolute <
			sSlowVectorArray[iSlow].Absolute  )
		{
			(*sMergedVectorArray)[iMerged].Absolute = sFastVectorArray[iFast].Absolute;
			(*sMergedVectorArray)[iMerged].iValue = 
				sFastVectorArray[iFast].iValue | sSlowVectorArray[iSlow - 1].iValue;
			iFast ++;
			continue;
		}
		if (sFastVectorArray[iFast].Absolute >
			sSlowVectorArray[iSlow].Absolute  )
		{
			(*sMergedVectorArray)[iMerged].Absolute = sSlowVectorArray[iSlow].Absolute;
			(*sMergedVectorArray)[iMerged].iValue = 
				sFastVectorArray[iFast - 1].iValue | sSlowVectorArray[iSlow].iValue;
			iSlow ++;
			continue;
		}
		if (sFastVectorArray[iFast].Absolute ==
			sSlowVectorArray[iSlow].Absolute  )
		{
			(*sMergedVectorArray)[iMerged].Absolute = sFastVectorArray[iFast].Absolute;
			(*sMergedVectorArray)[iMerged].iValue = 
				sFastVectorArray[iFast].iValue | sSlowVectorArray[iSlow].iValue;
			iFast ++;
			iSlow ++;
			continue;
		}
	}
	//Tails:
	//Fast tail
	iTail = iVectorsInFast - iFast;
	for (i = 0; i < iTail; i ++)
	{
		(*sMergedVectorArray)[iMerged + i].Absolute = sFastVectorArray[iFast].Absolute;
		(*sMergedVectorArray)[iMerged + i].iValue = 
			sFastVectorArray[iFast].iValue | sSlowVectorArray[iSlow - 1].iValue;
		iFast ++;
	}
	iMerged += i;
	//Slow tail
	iTail = iVectorsInSlow - iSlow;
	for ( i = 0; i < iTail; i ++)
	{
		(*sMergedVectorArray)[iMerged + i].Absolute = sSlowVectorArray[iSlow].Absolute;
		(*sMergedVectorArray)[iMerged + i].iValue = 
			sFastVectorArray[iFast - 1].iValue | sSlowVectorArray[iSlow].iValue;
		iSlow ++;
	}
	iMerged += i;
	return iMerged;
}
